#include "config.h"

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define DBG_SUBSYS S_LIBYLIB

#include "configure.h"
#include "config.h"
#include "confy.h"
#include "sysy_conf.h"
#include "sysutil.h"
#include "dbg_proto.h"

//#define DISK_CACHE_MAX 100
#define DISK_CACHE_ALIGN (1 * 1024 * 1024 * 1024LL)     /* 1G  */

extern FILE *yyin;

int line = 1;

struct sanconf_t sanconf;
struct nfsconf_t nfsconf;
struct webconf_t webconf;
struct mdsconf_t mdsconf;
struct cdsconf_t cdsconf;
struct gloconf_t gloconf;
struct logconf_t logconf;
netconf_t netconf;

static char config_path[MAX_PATH_LEN];

int get_nfs_export(const char *path, const char *ip, const char *permision)
{
        struct nfsconf_export_t _export;

#if 0
        DBUG("add path:%s, ip:%s, permision:%s\n",
                        path,
                        ip,
                        permision);
#endif

        strncpy(_export.path, path, strlen(path) + 1);

        strncpy(_export.ip, ip, strlen(ip) + 1);

        strncpy(_export.permision, permision, strlen(permision) + 1);

        memcpy(&nfsconf.nfs_export[nfsconf.export_size], &_export,
                        sizeof(struct nfsconf_export_t));

        nfsconf.export_size++;

        return 0;
}

int get_networks(const char *_ip)
{
        char addrs[MAX_NAME_LEN], *s;
        uint32_t mask, i, _mask;

        strcpy(addrs, _ip);

        s = strchr(addrs, '/');

        if (s == NULL) {
                exit(2);
        }

        *s = '\0';

        mask = atoi(s + 1);

        if (strlen(_ip) >= MAX_NAME_LEN) {
                exit(2);
        }

        if (netconf.count >= MAX_NET_COUNT) {
                exit(2);
        }

        netconf.network[netconf.count].network = inet_addr(addrs);
        netconf.network[netconf.count].mask = 0;

        //printf("network %u\n", netconf.network[netconf.count].network);

        _mask = 0;
        for (i = 0; i < mask; i++) {
                _mask |= 1<<(31-i);
        }

        netconf.network[netconf.count].mask = htonl(_mask);
        netconf.count++;

        return 0;
}

void yyerror(const char *str)
{
        fprintf(stderr, "config: parse %s error at line %d, %s\n",
               config_path, line, str);

        exit(1);
}

int yywrap() {
        return 1;
}

extern int yyparse();

int conf_init()
{
        int ret;

        snprintf(config_path, MAX_PATH_LEN, "%s/lich.conf", LICH_CONFIG_PATH);
        //snprintf(gloconf.home, MAX_PATH_LEN, "%s/..", LICH_CONFIG_PATH);

        /* default */
        cdsconf.disk_keep = (20 * 1024 * 1024 * 1024LL); /*20G*/
        cdsconf.disk_timeout = 60;
        cdsconf.ha_mode = 2;

        cdsconf.disk_cache = 0;
        cdsconf.cache_flush = 100;

        nfsconf.rsize = 1048576;
        nfsconf.wsize = 1048576;

        memset(sanconf.iqn, 0x0, MAXSIZE);
        sanconf.lun_blk_shift = 9;
        sanconf.iscsi_gateway = 0;
        sanconf.iscsi_port = 3260;
        sanconf.iscsi_vip.vip_count = 0;
        sanconf.ucarp_vip[0] = '\0';
        sanconf.iscsi_timeout = 300;
        sanconf.iser = 0;
        sanconf.tcp_discovery = 0;

        netconf.count = 0;

        gloconf.maxcore = 1;
        gloconf.coredump = 1;
        memset(gloconf.cluster_name, 0x0, MAXSIZE);
        strcpy(gloconf.default_protocol, "nbd");
        gloconf.chunk_rep = LICH_REPLICA_DEFAULT;
        gloconf.localize = 0;
        gloconf.writeback = 0;
        gloconf.priority = -1;
        gloconf.multipath = 0;
        gloconf.performance_analysis = 0;
        gloconf.net_crc = 0;
        gloconf.nohosts = 0;
        gloconf.crontab = 1;

        // network
        gloconf.rdma_base_port = LICH_RDMA_PORT;
        gloconf.rdma = 0;
        gloconf.spdk = 0;
        gloconf.huge_page = 0;
        gloconf.huge_page_reserved = 0;
        gloconf.nvme = 1;
        gloconf.nvme_stat = 0;
        gloconf.ring = 1;
        gloconf.control_port  = 7901;
        gloconf.data_port  = 17901;
        gloconf.direct_port  = LICH_DIRECT_PORT;
        gloconf.lichbd_port  = LICH_LICHBD_PORT;
        gloconf.rpc_timeout = 10;
        gloconf.hb_timeout = 2;
        gloconf.offline_timeout = 30;
        gloconf.hb_retry = 3;

        gloconf.polling_timeout = 0;
        strcpy(gloconf.polling_core, "2");
        strcpy(gloconf.aio_core, "0");
        gloconf.wmem_max = SO_XMITBUF;
        gloconf.rmem_max = SO_XMITBUF;
        gloconf.iscsid = 1;
        gloconf.nvmf = 0;
        gloconf.nfsd = 0;
        gloconf.cgroup = 0;
        gloconf.cleanlogcore = 1;
        gloconf.move_interval = (60);
        gloconf.restart = 1;
        gloconf.testing = 0;
        gloconf.main_loop_threads = 5;
        gloconf.lease_timeout = 5;
        gloconf.master_timeout = 5;
        gloconf.backtrace = 0;
        gloconf.solomode = 0;
        gloconf.cache_type = 2;
        gloconf.cache_enable = 1;
        gloconf.log_max_bytes = 104857600; //100 * 1024 * 1024 = 104857600 100M
        gloconf.storage_area_max_node = 20; //
        gloconf.force_write_repnum = 2; //
        gloconf.cleanup_thread = 10;

        gloconf.memcache_seg = 1024 * 1024 * 2;
        gloconf.memcache_count = 512;
        gloconf.metadata_replica = LICH_REPLICA_METADATA;
        gloconf.metadata_consistent = 1;

        gloconf.bitmap_cache_count = 512;
        gloconf.volume_crc = 0;
        gloconf.clock_unsafe = 0;
        gloconf.nodata_unsafe = 0;
        gloconf.read_modify_write = 0;

        gloconf.background_recovery = 1;
        gloconf.recovery_interval = 28800;

        gloconf.chunk_cleanup_msgqueue_size = CHUNK_CLEANUP_MSGQUEUE_DEFAULT_SIZE;

        gloconf.clock = 1;

        gloconf.lichbd = 1;
        strcpy(gloconf.lichbd_root, LICHBD_DEFAULT_NS);

        gloconf.redis_cache = 0;
        strcpy(gloconf.redis_sock, REDIS_DEFAULT_SOCK);

        gloconf.nbd = 1;
        gloconf.nbd_port = NBD_DEFAULT_PORT;
        strcpy(gloconf.nbd_sock, NBD_DEFAULT_SOCK);
        strcpy(gloconf.nbd_root, NBD_DEFAULT_ROOT);

        gloconf.sheepdog = 0;
        gloconf.sheepdog_port  = SD_DEFAULT_PORT;
        strcpy(gloconf.sheepdog_sock,  SD_DEFAULT_SOCK);
        strcpy(gloconf.sheepdog_root, SD_DEFAULT_ROOT);

        mdsconf.meta = 7;
        strcpy(gloconf.home, "/opt/fusionstack");
        gloconf.lichbd_cache[0] = '\0';
        strcpy(gloconf.cluster_name, "none");
        gloconf.kv_redis = 0;
        gloconf.bmap_mem = 0;
        gloconf.clock_mem = 1;
        gloconf.etcd_conn = 0;
        strcpy(sanconf.iqn, "none");

        yyin = fopen(config_path, "r");
        if (yyin == NULL) {
                ret = errno;
                fprintf(stderr, "open %s fail, ret %u\n", config_path, ret);
                goto err_ret;
        }

        yyparse();

        if (gloconf.rpc_timeout <= 2) {
                fprintf(stderr, "CONFIG: reqtimeout < 10, value: %d\n", gloconf.rpc_timeout);
                ret = EINVAL;
                goto err_ret;
        }

        return 0;
err_ret:
        return ret;
}

int conf_destroy(void)
{
        fclose(yyin);

        return 0;
}

LLU str2val(const char *str)
{
        LLU val;

        val = atoll(str);

        while (*str) {
                switch (*str) {
                        case 'k':
                        case 'K':
                                val *= 1024;
                                break;
                        case 'm':
                        case 'M':
                                val *= 1024 * 1024;
                                break;
                        case 'g':
                        case 'G':
                                val *= 1024 * 1024 * 1024;
                                break;
                        default:
                                break;
                }

                str += 1;
        }

        return val;
}


int keyis(const char *src, const char *dst)
{
        if (strcmp(src, dst) == 0)
                return 1;
        else
                return 0;
}

int var_get_type(const char *key, int *type)
{
        int ret;

        if (keyis("use_export", key))
                *type = V_NUMBER;
        else if (keyis("rsize", key))
                *type = V_NUMBER;
        else if (keyis("wsize", key))
                *type = V_NUMBER;
        /**
         * yiscsi configure
         */
        else if (keyis("iqn", key))
                *type = V_STRING;
        else if (keyis("iscsi_port", key))
                *type = V_NUMBER;
        else if (keyis("iscsi_vip", key))
                *type = V_STRING;
        else if (keyis("ucarp_vip", key))
                *type = V_STRING;
        else if (keyis("lun_blk_shift", key))
                *type = V_NUMBER;

        /**
         * yweb configure
         */
        else if (keyis("webport", key))
                *type = V_NUMBER;
        else if (keyis("use_ratelimit", key))
                *type = V_NUMBER;

        /**
         * mds configure
         */

        else if (keyis("meta", key))
                *type = V_NUMBER;

        /**
         * cds configure
         */
        else if (keyis("disk_keep", key))
                *type = V_NUMBER;
        else if (keyis("ha_mode", key))
                *type = V_NUMBER;
        else if (keyis("writeback_count", key))
                *type = V_NUMBER;
        else if (keyis("writeback", key))
                *type = V_NUMBER;
        /**
         * global configure
         */
        else if (keyis("performance_analysis", key))
                *type = V_NUMBER;

        else if (keyis("rpc_timeout", key))
                *type = V_NUMBER;
        else if (keyis("rpc_timeout", key))
                *type = V_NUMBER;
        else if (keyis("hb_timeout", key))
                *type = V_NUMBER;
        else if (keyis("iscsi_timeout", key))
                *type = V_NUMBER;
        else if (keyis("polling_timeout", key))
                *type = V_NUMBER;
        else if (keyis("polling_core", key))
                *type = V_STRING;
        else if (keyis("aio_core", key))
                *type = V_STRING;
        else if (keyis("chunk_rep", key))
                *type = V_NUMBER;
        else if (keyis("localize", key))
                *type = V_NUMBER;
        else if (keyis("writeback", key))
                *type = V_NUMBER;
        else if (keyis("priority", key))
                *type = V_NUMBER;
        else if (keyis("multipath", key))
                *type = V_NUMBER;
        else if (keyis("maxcore", key))
                *type = V_NUMBER;
        else if (keyis("coredump", key))
                *type = V_NUMBER;
        else if (keyis("clustername", key))
                *type = V_STRING;
        else if (keyis("clusterid", key))
                *type = V_NUMBER;
        else if (keyis("net_crc", key))
                *type = V_NUMBER;
        else if (keyis("control_port", key))
                *type = V_NUMBER;
        else if (keyis("data_port", key))
                *type = V_NUMBER;
        else if (keyis("direct_port", key))
                *type = V_NUMBER;
        else if (keyis("lichbd_port", key))
                *type = V_NUMBER;
        else if (keyis("home", key))
                *type = V_STRING;
        else if (keyis("cluster_name", key))
                *type = V_STRING;
        else if (keyis("uuid", key))
                *type = V_STRING;
        else if (keyis("wmem_max", key))
                *type = V_NUMBER;
        else if (keyis("rmem_max", key))
                *type = V_NUMBER;
        else if (keyis("crontab", key))
                *type = V_NUMBER;
        else if (keyis("nbd", key))
                *type = V_NUMBER;
        else if (keyis("lichbd", key))
                *type = V_NUMBER;
        else if (keyis("iscsid", key))
                *type = V_NUMBER;
        else if (keyis("nvmf", key))
                *type = V_NUMBER;
        else if (keyis("nfsd", key))
                *type = V_NUMBER;
        else if (keyis("nohosts", key))
                *type = V_NUMBER;
        else if (keyis("cgroup", key))
                *type = V_NUMBER;
        else if (keyis("cleanlogcore", key))
                *type = V_NUMBER;
        else if (keyis("move_interval", key))
                *type = V_NUMBER;
        else if (keyis("restart", key))
                *type = V_NUMBER;
        else if (keyis("testing", key))
                *type = V_NUMBER;
        else if (keyis("lichbd_cache", key))
                *type = V_STRING;
        else if (keyis("readahead", key))
                *type = V_NUMBER;
        else if (keyis("main_loop_threads", key))
                *type = V_NUMBER;
        else if (keyis("lease_timeout", key))
                *type = V_NUMBER;
        else if (keyis("backtrace", key))
                *type = V_NUMBER;
        else if (keyis("solomode", key))
                *type = V_NUMBER;
        else if (keyis("cache_type", key))
                *type = V_NUMBER;
        else if (keyis("cache_enable", key))
                *type = V_NUMBER;
        else if (keyis("log_max_bytes", key))
                *type = V_NUMBER;
        else if (keyis("storage_area_max_node", key))
                *type = V_NUMBER;
        else if (keyis("force_write_repnum", key))
                *type = V_NUMBER;
        else if (keyis("cleanup_thread", key))
                *type = V_NUMBER;
        else if (keyis("memcache_seg", key))
                *type = V_NUMBER;
        else if (keyis("redis_cache", key))
                *type = V_NUMBER;
        else if (keyis("memcache_count", key))
                *type = V_NUMBER;
        else if (keyis("default_protocol", key))
                *type = V_STRING;
        else if (keyis("sheepdog", key))
                *type = V_NUMBER;
        else if (keyis("sheepdog_port", key))
                *type = V_NUMBER;
        else if (keyis("sheepdog_sock", key))
                *type = V_STRING;
        else if (keyis("sheepdog_root", key))
                *type = V_STRING;
        else if (keyis("lichbd_root", key))
                *type = V_STRING;
        else if (keyis("nbd_root", key))
                *type = V_STRING;
        else if (keyis("bitmap_cache_count", key))
                *type = V_NUMBER;
        else if (keyis("chunk_cleanup_msgqueue_size", key))
                *type = V_NUMBER;
        else if (keyis("hugepage", key))
                *type = V_NUMBER;
        else {
                ret = EINVAL;
                goto err_ret;
        }

        return 0;
err_ret:
        return ret;
}

static int __parse_vip_list(const char *iplist)
{
        char tmp[MAX_BUF_LEN], *p1, *p2;
        int i = 0;

        memset(tmp, 0, MAX_BUF_LEN);
        strcpy(tmp, iplist);
        p1 = tmp;

        while (*p1 != '\0') {
                p2 = strchr(p1, ',');
                if (p2 != NULL) {
                        *p2 = '\0';
                        strcpy(sanconf.iscsi_vip.vip[i++], p1);
                        sanconf.iscsi_vip.vip_count ++;
                } else {
                        break;
                }

                p1 = p2 + 1;
        }

        strcpy(sanconf.iscsi_vip.vip[i], p1);
        sanconf.iscsi_vip.vip_count ++;

        return 0;
}

int var_set(const char* key, const char* value, int type)
{
        int ret, vallen;
        LLU _value = 0;

        vallen = strlen(value);

#if 0
        int keylen;
        keylen = strlen(key);
        printf("%s : %s\n", key, value);
#endif

        if (type == V_NUMBER)
                _value = str2val(value);
        else if (type == V_STATE) {
                if (strncasecmp("on", value, vallen) == 0)
                        _value = 1;
                else
                        _value = 0;
        }

        /**
         * ynfs configure
         */
        if (keyis("use_export", key))
                nfsconf.use_export = _value;
        else if (keyis("rsize", key))
                nfsconf.rsize = _value;
        else if (keyis("wsize", key))
                nfsconf.wsize = _value;

        /**
         * yiscsi configure
         */
        else if (keyis("iqn", key))
                strncpy(sanconf.iqn, value, MAXSIZE);
        else if (keyis("iscsi_port", key))
                sanconf.iscsi_port = _value;
        else if (keyis("iscsi_gateway", key))
                sanconf.iscsi_gateway = _value;
        else if (keyis("iscsi_vip", key))
                __parse_vip_list(value);
        else if (keyis("iscsi_timeout", key))
                sanconf.iscsi_timeout = _value;
        else if (keyis("iser", key))
                sanconf.iser = _value;
        else if (keyis("tcp_discovery", key))
                sanconf.tcp_discovery = _value;
        else if (keyis("ucarp_vip", key))
                strncpy(sanconf.ucarp_vip, value, MAXSIZE);
        else if (keyis("lun_blk_shift", key)) {
                if (_value < 9 || _value > 12) {
                        fprintf(stderr, "lun_blk_shift must between [9, 12]\n");
                } else
                        sanconf.lun_blk_shift = _value;
        }

        /**
         * yweb configure
         */
        else if (keyis("webport", key))
                webconf.webport = _value;
        else if (keyis("use_ratelimit", key))
                webconf.use_ratelimit = _value;

        /**
         * mds configure
         */

        else if (keyis("meta", key)) {
                mdsconf.meta = _value;
                if (mdsconf.meta < 3)
                        mdsconf.meta = 3;
        }

        /**
         * cds configure
         */
        else if (keyis("disk_keep", key))
                cdsconf.disk_keep = _value;
        else if (keyis("disk_cache", key)) {
                if (_value > 100) {
                        _value = 100;
                }
                cdsconf.disk_cache = _value;
        } else if (keyis("ha_mode", key))
                cdsconf.ha_mode = _value;
        else if (keyis("cache_flush", key))
                cdsconf.cache_flush = _value;
        /**
         * global configure
         */
        else if (keyis("performance_analysis", key))
                gloconf.performance_analysis = _value;
        else if (keyis("redis_cache", key))
                gloconf.redis_cache = _value;

        else if (keyis("rpc_timeout", key))
                gloconf.rpc_timeout = _value;
        else if (keyis("offline_timeout", key))
                gloconf.offline_timeout = _value;
        else if (keyis("hb_timeout", key))
                if (_value < 1 || _value > 10) {
                        fprintf(stderr, "hb_timeout must between [2, 10]\n");
                } else
                        gloconf.hb_timeout = _value;
        else if (keyis("hb_retry", key))
                if (_value < 1 || _value > 10) {
                        fprintf(stderr, "hb_retry must between [2, 10]\n");
                } else
                        gloconf.hb_retry = _value;
        else if (keyis("iscsi_timeout", key))
                sanconf.iscsi_timeout = _value;
        else if (keyis("polling_timeout", key))
                gloconf.polling_timeout = _value;
        else if (keyis("polling_core", key)) {
                strncpy(gloconf.polling_core, value, MAXSIZE);
        } else if (keyis("aio_core", key)) {
                strncpy(gloconf.aio_core, value, MAXSIZE);
        } else if (keyis("chunk_rep", key)) {
                gloconf.chunk_rep = _value;

                if (gloconf.chunk_rep > LICH_REPLICA_MAX)
                        gloconf.chunk_rep = LICH_REPLICA_MAX;
        }

        else if (keyis("clock", key))
                gloconf.clock = _value;
        else if (keyis("localize", key))
                gloconf.localize = _value;
        else if (keyis("writeback", key))
                gloconf.writeback = _value;
        else if (keyis("priority", key))
                gloconf.priority = _value;
        else if (keyis("multipath", key))
                gloconf.multipath = _value;
        else if (keyis("maxcore", key))
                gloconf.maxcore = _value;
        else if (keyis("coredump", key))
                gloconf.coredump = _value;
        else if (keyis("clustername", key))
                strncpy(gloconf.cluster_name, value, MAXSIZE);
        else if (keyis("clusterid", key))
                gloconf.cluster_id  = _value;
        else if (keyis("net_crc", key))
                gloconf.net_crc  = _value;
        else if (keyis("control_port", key))
                gloconf.control_port  = _value;
        else if (keyis("data_port", key))
                gloconf.data_port  = _value;
        else if (keyis("direct_port", key))
                gloconf.direct_port  = _value;
        else if (keyis("lichbd_port", key))
                gloconf.lichbd_port  = _value;
        else if (keyis("home", key))
                strcpy(gloconf.home, value);
        else if (keyis("kv_engine", key))
                if (strcmp(value, "redis") == 0) {
                        gloconf.kv_redis = 1;
                        gloconf.bmap_mem = 1;
                } else {
                        gloconf.kv_redis = 0;
                        gloconf.bmap_mem = 0;
                }
        else if (keyis("uuid", key)) {
                if (strlen(value) != 32)
                        fprintf(stderr, "%s:%s length is not 32\n", key, value);
                strcpy(gloconf.uuid, value);
        } else if (keyis("wmem_max", key))
                gloconf.wmem_max = _value;
        else if (keyis("rmem_max", key))
                gloconf.rmem_max = _value;
        else if (keyis("crontab", key))
                gloconf.crontab = _value;
        else if (keyis("nbd", key))
                gloconf.nbd = _value;
        else if (keyis("lichbd", key))
                gloconf.lichbd = _value;
        else if (keyis("iscsid", key))
                gloconf.iscsid = _value;
        else if (keyis("nvmf", key))
                gloconf.nvmf = _value;
        else if (keyis("nfsd", key))
                gloconf.nfsd = _value;
        else if (keyis("nohosts", key))
                gloconf.nohosts = _value;
        else if (keyis("cgroup", key))
                gloconf.cgroup = _value;
        else if (keyis("cleanlogcore", key))
                gloconf.cleanlogcore = _value;
        else if (keyis("move_interval", key))
                gloconf.move_interval = _value;
        else if (keyis("restart", key))
                gloconf.restart = _value;
        else if (keyis("testing", key))
                gloconf.testing = _value;
        else if (keyis("lichbd_cache", key))
                strcpy(gloconf.lichbd_cache, value);
        else if (keyis("main_loop_threads", key))
                gloconf.main_loop_threads = _value;
        else if (keyis("rdma", key))
                gloconf.rdma = _value;
        else if (keyis("spdk", key))
                gloconf.spdk = _value;
        else if (keyis("hugepage", key))
                gloconf.huge_page = _value;
        else if (keyis("hugepage_reserved", key))
                gloconf.huge_page_reserved = _value;
        else if (keyis("nvme", key))
                gloconf.nvme = _value;
        else if (keyis("nvme_stat", key))
                gloconf.nvme_stat = _value;
        else if (keyis("ring", key))
                gloconf.ring = _value;
        else if (keyis("lease_timeout", key))
                gloconf.lease_timeout = _value;
        else if (keyis("master_timeout", key))
                gloconf.master_timeout = _value;
        else if (keyis("backtrace", key))
                gloconf.backtrace = _value;
        else if (keyis("solomode", key))
                gloconf.solomode = _value;
        else if (keyis("cache_type", key))
                gloconf.cache_type = _value;
        else if (keyis("cache_enable", key))
                gloconf.cache_enable = _value;
        else if (keyis("log_max_bytes", key))
                gloconf.log_max_bytes = _value;
        else if (keyis("storage_area_max_node", key))
                gloconf.storage_area_max_node = _value;
        else if (keyis("force_write_repnum", key))
                gloconf.force_write_repnum = _value;
        else if (keyis("cleanup_thread", key))
                gloconf.cleanup_thread = _value;
        else if (keyis("memcache_seg", key))
                gloconf.memcache_seg = _value;
        else if (keyis("memcache_count", key))
                gloconf.memcache_count = _value;
        else if (keyis("default_protocol", key))
                strcpy(gloconf.default_protocol, value);
        else if (keyis("sheepdog", key))
                gloconf.sheepdog = _value;
        else if (keyis("sheepdog_port", key))
                gloconf.sheepdog_port = _value;
        else if (keyis("sheepdog_sock", key))
                strcpy(gloconf.sheepdog_sock, value);
        else if (keyis("sheepdog_root", key))
                strcpy(gloconf.sheepdog_root, value);
        else if (keyis("lichbd_root", key))
                strcpy(gloconf.lichbd_root, value);
        else if (keyis("nbd_root", key))
                strcpy(gloconf.nbd_root, value);
        else if (keyis("bitmap_cache_count", key))
                gloconf.bitmap_cache_count = _value;
        else if (keyis("volume_crc", key))
                gloconf.volume_crc = _value;
        else if (keyis("chunk_cleanup_msgqueue_size", key))
                gloconf.chunk_cleanup_msgqueue_size = _value;
        else if (keyis("clock_unsafe", key))
                gloconf.clock_unsafe = _value;
        else if (keyis("clock_mem", key))
                gloconf.clock_mem = _value;
        else if (keyis("etcd_conn", key))
                gloconf.etcd_conn = _value;
        else if (keyis("nodata_unsafe", key))
                gloconf.nodata_unsafe = _value;
        else if (keyis("read_modify_write", key))
                gloconf.read_modify_write = _value;
        else if (keyis("metadata_replica", key))
                gloconf.metadata_replica = _value;
        else if (keyis("metadata_consistent", key))
                gloconf.metadata_consistent = _value;
        else if (keyis("background_recovery", key))
                gloconf.background_recovery = _value;
        else if (keyis("recovery_interval", key))
                gloconf.recovery_interval = _value;
        /**
         * error.
         */
        else {
                fprintf(stderr, "%s:%s no such key_value\n", key, value);
                ret = EINVAL;
                goto err_ret;
        }

        return 0;
err_ret:
        return ret;
}

int var_get(const char* key, char *value)
{
        int ret;

        /*now , only performance_analysis can be use ! */
        if (keyis("performance_analysis", key))
                sprintf(value, "%s", gloconf.performance_analysis == 1 ? "1":"0");
        else {
                ret = EINVAL;
                goto err_ret;
        }

        return 0;
err_ret:
        return ret;
}

void conf_dump()
{
        // 打印系统配置参数
        DINFO("cluster %s cluster_id %d uuid %s home %s performance_analysis %d\n",
              gloconf.cluster_name,
              gloconf.cluster_id,
              gloconf.uuid,
              gloconf.home,
              gloconf.performance_analysis);

        DINFO("control_port %d data_port %d\n",
              gloconf.control_port,
              gloconf.data_port);

        DINFO("rpc_timeout %d hb_timeout %d lease_timeout %d pooling_timeout %d\n",
              gloconf.rpc_timeout,
              gloconf.hb_timeout,
              gloconf.lease_timeout,
              gloconf.polling_timeout);

        DINFO("memcache_seg %d memcache_count %d\n",
              gloconf.memcache_seg,
              gloconf.memcache_count);

        DINFO("recovery onoff %d interval %u\n",
              gloconf.background_recovery,
              gloconf.recovery_interval);
}
